﻿
using System.Collections.Generic;

using System.IO;
using ZXing;
using ZXing.Common;
using ZXing.QrCode.Internal;
#if NETFRAMEWORK
using System.Drawing;
using System.Drawing.Imaging;
#else
using ZXing.SkiaSharp;
using SkiaSharp;
#endif
namespace WebSelfHost.Utility.Files
{
    public class QRCodeUtils
    {
#if !NETFRAMEWORK
        public static SKImage EncodeQRCodeSKImage(string msg, int codeSizeInPixels = 900)
        {
            Dictionary<EncodeHintType, object> hints = new Dictionary<EncodeHintType, object>();
            hints.Add(EncodeHintType.CHARACTER_SET, "utf-8");
            hints.Add(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            hints.Add(EncodeHintType.MARGIN, 1);
            BitMatrix matrix = new MultiFormatWriter().encode(msg, BarcodeFormat.QR_CODE, codeSizeInPixels, codeSizeInPixels, hints);
            var info = new SKImageInfo(codeSizeInPixels, codeSizeInPixels);

            using (var surface = SKSurface.Create(info))
            {
                var canvas = surface.Canvas;
                for (int x = 0; x < matrix.Width; x++)
                {
                    for (int y = 0; y < matrix.Height; y++)
                    {

                        if (matrix[x, y])
                        {
                            canvas.DrawRect(x, y, 1, 1, new SKPaint
                            {
                                Color = SKColors.Black,
                                Style = SKPaintStyle.Fill
                            });
                        }
                    }
                }
                return surface.Snapshot();
            }
        }
        public static SKData EncodeQRCodeSKData(string msg, int codeSizeInPixels = 900)
        {
            using (var image = EncodeQRCodeSKImage(msg, codeSizeInPixels))
            {
                return image.Encode(SKEncodedImageFormat.Png, 100);
            }
        }
        public static byte[] EncodeQRCodeBytes(string msg, int codeSizeInPixels = 900)
        {
            using (var data = EncodeQRCodeSKData(msg, codeSizeInPixels))
            {
                return data.ToArray();
            }
        }
#else
        public static Image EncodeQRCodeImage(string msg, int codeSizeInPixels = 900)
        {
            Dictionary<EncodeHintType, object> hints = new Dictionary<EncodeHintType, object>();
            hints.Add(EncodeHintType.CHARACTER_SET, "utf-8");
            hints.Add(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            hints.Add(EncodeHintType.MARGIN, 1);
            BitMatrix matrix = new MultiFormatWriter().encode(msg, BarcodeFormat.QR_CODE, codeSizeInPixels, codeSizeInPixels, hints);
            Bitmap bmap = new Bitmap(matrix.Width, matrix.Height, PixelFormat.Format32bppArgb);
            for (int x = 0; x < matrix.Width; x++)
            {
                for (int y = 0; y < matrix.Height; y++)
                {
                    if (matrix[x, y])
                        bmap.SetPixel(x, y, Color.Black);
                }
            }
            return bmap;
        }

        public static byte[] EncodeQRCodeBytes(string msg, int codeSizeInPixels = 900)
        {
            using (MemoryStream mostream = new MemoryStream())
            {
                using (var data = EncodeQRCodeImage(msg, codeSizeInPixels))
                {
                    data.Save(mostream, ImageFormat.Png);
                    byte[] bt = new byte[mostream.Length];
                    mostream.Position = 0;//设置留的初始位置
                    mostream.Read(bt, 0, bt.Length);
                    return bt;
                }
            }
        }
#endif

#if !NETFRAMEWORK
        public static string DecodeQRCode(string filePath)
        {
            using (var original = SKBitmap.Decode(filePath))
            {
                return DecodeQRCode(original);
            }
        }

        private static string DecodeQRCode(SKBitmap bitmap)
        {
#if NETFRAMEWORK
            Result result = new ZXing.BarcodeReader().Decode(new SKBitmapLuminanceSource(bitmap));
#else
            Result result = new BarcodeReader<LuminanceSource>((source) =>
            {
                return new SKBitmapLuminanceSource(bitmap);
            }).Decode(bitmap);
#endif
            return result.Text;
        }

        public static string DecodeQRCode(SKImage image)
        {
            using (var data = image.Encode(SKEncodedImageFormat.Png, 100))
            {
                using (var original = SKBitmap.Decode(data))
                {
                    return DecodeQRCode(original);
                }
            }
        }
        public static string DecodeQRCode(SKData data)
        {
            using (var original = SKBitmap.Decode(data))
            {
                return DecodeQRCode(original);
            }
        }

        public static string DecodeQRCode(Stream stream)
        {
            using (var original = SKBitmap.Decode(stream))
            {
                return DecodeQRCode(original);
            }
        }
        public static string DecodeQRCode(byte[] data)
        {
            using (var original = SKBitmap.Decode(data))
            {
                return DecodeQRCode(original);
            }
        }
#endif
    }

}
